/**
*   @brief Singleton pattern.
*
*   <p>Provide an implementation of the singleton pattern by subclassing.</p>
*   <p>Subclasses have to use the CRTP idiom and declare it friendly.</p>
*/

#ifndef SINGLETON_H
#define SINGLETON_H

#include <cstdlib>

#include "Concurrent/Mutex.hpp"
#include "Debug/Memory.hpp"
#include "Pattern/Uncopyable.hpp"

namespace My
{
    template< class C >
    class Singleton : private Uncopyable
    {
    public:
        /**
        *   @brief Return the active instance.
        *
        *   <p>The singleton is actually only created during first call.</p>
        *
        *   @warning After this method is called, make sure to call the corresponding
        *   cleanup method Release().
        *
        *   @threadsafe
        *
        *   @see Release()
        */
        static C& Get();

        /**
        *   @brief Release the active instance.
        *
        *   <p>Perform the cleanup after singleton instanciation.</p>
        *
        *   @warning After Get() is called, make sure to call this method to
        *   perform cleanup.
        *
        *   @threadsafe
        *
        *   @see Get()
        */
        static void Release();

    private:
        static Mutex s_Mutex;

        static C* s_Instance;
    };

    template< class C >
    C& Singleton< C >::Get()
    {
        s_Mutex.Lock();

        if(!s_Instance)
           s_Instance = MY_NEW C;

        s_Mutex.Unlock();

        return *s_Instance;
    }

    template< class C >
    void Singleton< C >::Release()
   {
       s_Mutex.Lock();

       MY_DELETE s_Instance;
       s_Instance = NULL;

       s_Mutex.Unlock();
   }

    template< class C >
    Mutex Singleton< C >::s_Mutex(true);

    template< class C >
    C* Singleton< C >::s_Instance = NULL;
}

#endif // SINGLETON_H
